Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature/#17] refresh token 발급 시 Redis에 저장하도록 설정 #18

Merged
merged 19 commits into from
Aug 16, 2023

Conversation

Mingyum-Kim
Copy link
Collaborator

1️⃣ 작업 내용 (Contents)

resolved : #17

  1. Redis 설치 및 RedisConfig 작성
  2. AuthController에서 refresh 함수 작성
  3. AuthService에서 로그인 시 refresh token을 Redis에 저장하는 코드 작성
  4. AuthService에서 access token을 재발급하는 로직 작성
  5. RefreshTokenDao, RefreshTokenRepository 작성
  6. RefreshTokenService 작성
  7. Redis 서버 호출 테스트 (RefreshTokenRepository), AuthService 통합 테스트 작성

2️⃣ 링크 (Links)

3️⃣ 희망 리뷰 완료 일 (Expected due date)

오늘

4️⃣ 기타 사항 (ETC)

@Mingyum-Kim Mingyum-Kim added the feature New feature or request label Aug 16, 2023
@Mingyum-Kim Mingyum-Kim self-assigned this Aug 16, 2023
@@ -31,6 +31,7 @@ dependencies {
// database
implementation 'org.mariadb.jdbc:mariadb-java-client:3.1.4'
runtimeOnly 'com.h2database:h2'
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

build.gradle에 redis 라이브러리 추가했습니다! 로컬에서도 Redis 프로그램을 localhost:6379 환경으로 세팅해야 관련 코드가 정상적으로 동작합니다:)


@Service
@RequiredArgsConstructor
public class RefreshTokenService {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redis에 RefreshToken을 저장, 조회하기 위한 서비스 클래스입니다!

Comment on lines +41 to 49
public String generateToken(String uid, Long expireTime){
Date now = new Date();
return Jwts.builder()
.setSubject(member.getSocialId())
.setSubject(uid)
.setIssuedAt(now)
.setExpiration(new Date(now.getTime() + expireTime))
.signWith(key, SignatureAlgorithm.HS256)
.compact();
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

실제 JWT 생성 과정에서 uid(구 socialId)만 사용하기 때문에 uid만 필드에 받아오는 것으로 변경하였습니다.

Comment on lines 71 to 78
} catch (ExpiredJwtException e){
throw e;
throw new BusinessException(ErrorCode.TOKEN_EXPIRED);
} catch (UnsupportedJwtException e){
throw e;
throw new BusinessException(ErrorCode.INVALID_TOKEN);
} catch (MalformedJwtException e) {
throw new BusinessException(ErrorCode.MALFORMED_TOKEN);
} catch (IllegalArgumentException e){
throw e;
throw new BusinessException(ErrorCode.TOKEN_ERROR);
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

jwt 라이브러리에 선언된 예외가 잡히면 저희가 만든 BusinessException을 던지도록 설정하였습니다. (통일성 있는 점은 좋은데 jwt 라이브러리에서 제공하는 예외 클래스를 사용하는게 더 자세한 정보를 제공하면서 코드도 직관적이지 않나? 라는 생각도 했습니다!)

Copy link
Collaborator

@jemlog jemlog Aug 16, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Token Expired는 Business 예외를 정의해도 괜찮을 것 같은데, 나머지 예외들은 그냥 exception.class를 처리하는 exceptionHandler에서 처리해도 괜찮다는 생각이 들어요!

description = "access token 만료 시 refresh token을 통해 access token을 재발급합니다.")
@PostMapping("/reissue")
public ResponseEntity<CustomResponse> reissue(@RequestBody TokenReissueRequest reissueRequest){
return CustomResponse.success(SELECT_SUCCESS, oauthService.reissue(reissueRequest.refreshToken()));
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OAuthController의 컨트롤러 반환 시 CustomReponse에 어떤 SuccessCode를 담아야 할 지 살짝 난감했습니다. 로그인 시에는 MemberService에서 사용자 조회 & Redis에 저장하기도 하고, reissue에는 Redis에서 조회만 하니 이렇게 설정했는데, 의견있으시면 남겨주세요!

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

음 ErrorCode에 보니 LOGIN_SUCCESS 만들어놓으셨던데 인증 관련은 그걸로 통일해도 되지 않을까요?!

Comment on lines 19 to 22
public RefreshToken findUidByRefreshToken(String refreshToken){
return refreshTokenRepository.findById(refreshToken)
.orElseThrow(() -> new BusinessException(ErrorCode.NOT_FOUND_ERROR));
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

findUidByRefreshToken 이라는 메서드 명칭인데 반환값이 Uid가 아니라 RefreshToken이네요! 이유가 있을까요?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redis에서 refreshToken을 key로 하여 반환 시 uid가 아니라 (refreshToken, uid) 쌍이 반환되더라구요 !! (이 dao 이름을 RefreshToken으로 설정해서 저런 일이 생긴건데, uid를 꺼내서 반환하는걸로 수정할게요 ~

Comment on lines 71 to 78
} catch (ExpiredJwtException e){
throw e;
throw new BusinessException(ErrorCode.TOKEN_EXPIRED);
} catch (UnsupportedJwtException e){
throw e;
throw new BusinessException(ErrorCode.INVALID_TOKEN);
} catch (MalformedJwtException e) {
throw new BusinessException(ErrorCode.MALFORMED_TOKEN);
} catch (IllegalArgumentException e){
throw e;
throw new BusinessException(ErrorCode.TOKEN_ERROR);
Copy link
Collaborator

@jemlog jemlog Aug 16, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Token Expired는 Business 예외를 정의해도 괜찮을 것 같은데, 나머지 예외들은 그냥 exception.class를 처리하는 exceptionHandler에서 처리해도 괜찮다는 생각이 들어요!


@Enumerated(value = EnumType.STRING)
@Column(nullable = false, length = 15)
private SocialType socialType;
private Provider provider;

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

지금 보니깐 궁금한게 있는데 provider에 15자 제한이 있는 이유가 있나요?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DB에 varchar(15) 이렇게 정의되어있던 것 같아서 저렇게 설정했고 큰 의미는 없습니다 !

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아하 그러면 굳이 안붙여도 될것 같다는 생각이 들어요! 의미 없는 코드가 많아지면 나중에 헷갈리더라구요! 🥲


MALFORMED_TOKEN(BAD_REQUEST.value(), "AUTH-003", "잘못된 구조의 토큰이 입력되었습니다."),

TOKEN_ERROR(BAD_REQUEST.value(), "AUTH-004" ,"토큰 검증 시 알 수 없는 오류가 발생했습니다." );

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

음 여기서는 토큰 유효기간이 만료됐다는 메세지만 만들고 나머지는 exception를 잡는 exceptionHandler에 걸려서 reason 컬럼으로 에러가 출력되도록 해도 될것 같아요! 기본 JWT 예외를 사용하는게 어떻겠냐는 부분에 대한 답도 되는것 같습니다~

description = "access token 만료 시 refresh token을 통해 access token을 재발급합니다.")
@PostMapping("/reissue")
public ResponseEntity<CustomResponse> reissue(@RequestBody TokenReissueRequest reissueRequest){
return CustomResponse.success(SELECT_SUCCESS, oauthService.reissue(reissueRequest.refreshToken()));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

음 ErrorCode에 보니 LOGIN_SUCCESS 만들어놓으셨던데 인증 관련은 그걸로 통일해도 되지 않을까요?!

description = "access token 만료 시 refresh token을 통해 access token을 재발급합니다.")
@PostMapping("/reissue")
public ResponseEntity<CustomResponse> reissue(@RequestBody TokenReissueRequest reissueRequest){
return CustomResponse.success(SELECT_SUCCESS, oauthService.reissue(reissueRequest.refreshToken()));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 부분 혹시 TokenReissueRequest 앞에 @Valid 붙여야 하지 않나요?!

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

헉 .. 붙였는데 리뷰하신 후에 커밋한 것 같슴니다

Comment on lines +5 to +8
public record TokenReissueRequest(
@NotNull(message = "access token reissue 시 refresh token 입력은 필수입니다.")
String refreshToken
) { }
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

궁금한 부분이 있는데요, reissue를 하는 과정에서 그럼 발생할 수 있는 문제가

  1. 토큰을 못 찾아서 발생하는 not found 커스텀 에러
  2. 토큰을 아예 안넘겨서 발생하는 binding 에러
  3. 토큰 validation 과정에서 발생하는 에러
    이렇게 발생할 것 같은데, 프론트에는 뭐든 에러가 발생하면 재로그인 로직으로 넘어가도록 인계하는 걸까요?!

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

코드에 문제가 있는게 아니라 궁금증 입니다😊

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. RefreshTokenService의 find 함수에서 처리하였습니다 !
  2. Dto의 @NotNull 어노테이션을 이용한 검증 이외의 추가 validation이 필요할까요 ??
  3. 그 부분은 한 번 찾아봐야 할 것 같습니다 !! 객체를 반환하는 것 이외에 redirect하는 방식을 말씀하신걸까요?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. 넵넵! 확인했습니다~
  2. 더 필요하지 않을것 같아요! 사실 notnull의 필요성도 그리 크지 않다고 생각이 되요!!
  3. 음..이부분은 서버에서는 딱히 신경 안써도 될것 같긴해요!! 리프레시 API를 프론트가 호출하고, 거기서 어떤 예외든 반환되면 로그인 화면으로 이동 시키면 되니 서버는 상관 없을것 같네요!

@Mingyum-Kim Mingyum-Kim merged commit a3da0fc into dev Aug 16, 2023
1 check failed
@Mingyum-Kim Mingyum-Kim deleted the feature/#17 branch August 16, 2023 12:47
Mingyum-Kim added a commit that referenced this pull request Sep 17, 2023
* 상위 목표 엔티티 구현 (#5)

* chore: Lombok, JPA 의존성 추가

* feat: plan 엔티티 내 유효성 검사 구현

* feat: PlanRepository 생성

* test: plan 엔티티 테스트 작성

- 상위 목표 제목 길이 validation 테스트
- 상위 목표 시작, 달성 날짜 validation 테스트
- 상위 목표 제목 길이 Figma 참고해서 15자 제한

* feat: 상위 목표 기간 LocalDate 타입으로 변경 (#3)

기간을 설정할때 연월일 까지만 데이터를 받기에 시,분까지 데이터를 받는 LocalDateTime은 불필요하다고 판단했음.

* [Feature/#2] 소셜 로그인 구현 (#4)

* feat: BaseEntity 작성

global/entity 폴더에 created_at, updated_at 필드를 넣는 BaseEntity 클래스를 작성하였습니다.

* feat: User Entity 생성 (#2)

DB에 매핑될 User 객체를 생성하였습니다. Kakao, Apple 두 개의 소셜 타입을 구분할 SocialType 필드를 enum Type으로 추가하였습니다.

* chore: Swagger, Logging 클래스 global 폴더로 이동

* feat: OAuthController 생성 및 콜백 메서드 생성

1. 클라이언트가 AccessToken을 전달할 때 접근하는 'POST /auth' 콜백 주소를 연결할 메서드를 생성하였습니다.
2. 컨트롤러 메서드의 request, response dto를 record 클래스로 정의하였습니다.

* feat: login 로직을 구현한 OAuthService 생성

1. 팩토리 메서드 패턴을 적용하여 OAuthClient 인터페이스를 provider에 따라 구현체를 매핑하도록 설정하였습니다.
2. OAuthClient에서 소셜 사용자의 정보를 불러오고 User 객체로 변환하였습니다.
3. User가 기 가입한 회원이라면 바로 반환, 그렇지 않다면 DB에 등록 후 반환하기 위해 UserService에서 로직을 구현하였습니다.
4. 마지막으로 회원에 대한 JWT 를 발급하여 반환하였습니다.

* build: syntax error 수정

* build: syntax error 수정

* build: Junit Test 관련 권한 추가

* feat: WebClient를 이용해 카카오 인증서버에서 사용자 추출 (#2)

KakaoClient 구현체에서 WebClient 라이브러리를 사용해 kapi.kakao.com 서버에 접근하여 사용자 정보 (KakaoUserInfo)를 추출하는 코드입니다.

* feat: JwtProvider 클래스 생성

1. createToken 메서드
2. validateToken 메서드

* chore: .gitignore 수정

* feat: 애플 로그인 구현

* refactor: OAuthHandler에서 Provider별 클래스 분리 구현

* test: OAuthServiceTest 로그인 성공 테스트 생성(#2)

* feat: KakaoClient BASE_URL과 URI 분리

* style: dto 폴더구조 request, response 나눠서 변경

* refactor: SocialId만 이용해서 사용자 조회하도록 변경

* refactor: BaseEntity에 자동으로 날짜를 주입하도록 설정

---------

Co-authored-by: MingyeomKim <[email protected]>

* [Feature/#7] 설정 파일 submodule로 관리 (#8)

* build: db 정보 암호화를 위한 submodules 설정(#7)

* build: github Secrets 설정 수정

* fix: build.yml의 들여쓰기 오류 수정

* feat: 빌드 시 submodule 설정 파일 불러올 수 있도록 build.gradle 수정

* build: deploy.yml ACTION_TOKEN 추가

* build: build.gradle 라이브러리 중복 제거

* "build: build.gradle에 active profile 설정 추가 (#7) "

* feat: dev 환경 데이터베이스 설정 추가

* build: dev 환경에서 빌드되도록 수정

* fix: build.yml의 test 명령어 수정

* fix: build.yml의 Publish unit test r구문 수정

* fix: build.yml test 파일 경로 수정"

* "build: test 시 h2 database에서 작동하도록 application-tets.yml 추가

* chore: .gitignore 수정

* build: test profile을 test로 변경

* test: config 설정 수정

* build: build.yml의 Publish Unit Test Results에 토큰 추가

* build: test-results files 경로 수정

* build: github actions permissions를 write 권한으로 변경

* build: build.yml에 issues: write 권한 추가

* refactor: User 명칭을 Member로 변경

---------

Co-authored-by: MingyeomKim <[email protected]>

* [Feature/#6] 공통 응답 추가 및 상위 목표 단건 조회 기능 구현 (#9)

* feat: 상위 목표 d-day 기능 구현, 테스트 작성 (#6)

- 상위 목표 종료 일자 필수 입력으로 확정 후, d-day 계산 로직 plan 엔티티내 생성 후 테스트
- planService에 상위 목표 단건 조회 로직 추가

* feat: 공통 응답 스펙 추가

* feat: 상위 목표 삭제 기능 추가

- Service에 삭제 기능 추가, 차후 테스트 필요
- 상위 목표 생성 Controller DTO 추가

* chore: application.yml 수정

* test: CI 테스트

* refactor: controller내 pathVariable 제거

* chore: build.yml을 테스트 환경에서 동작하도록 수정

* refactor: 소셜 로그인 시 input을 userId로 맞추어 수정 (#11) (#12)

Co-authored-by: MingyeomKim <[email protected]>

* [Feature/#13] TokenProvider 클래스 생성 및 Refresh Token 반환 (#14)

* feat: Refresh token을 생성하도록 TokenProvider 클래스 추가

* test: TokenProvider 단위 테스트 생성

* test: TokenProviderTest 오류 수정

---------

Co-authored-by: MingyeomKim <[email protected]>

* [Feature/#10] 상위 목표 리스트 조회 기능 구현 (#15)

* feat: 상위 목표 d-day 기능 구현, 테스트 작성 (#6)

- 상위 목표 종료 일자 필수 입력으로 확정 후, d-day 계산 로직 plan 엔티티내 생성 후 테스트
- planService에 상위 목표 단건 조회 로직 추가

* chore: git 캐시 초기화

* feat: 상위 목표 생성, 수정 기능 구현 (#10)

* refactor: 상위 목표 도메인 명을 Plan에서 Goal로 변경

- Goal이라는 단어가 목표라는 의미를 더 잘 표현하는 것 같아서 변경하게 되었습니다

* refactor: 공통 응답 스펙명 CustomResponse로 변경

- Swagger에 있는 ApiResponse와 네이밍이 같아서 패키지 명 전체를 명시해야 함. 따라서 customResponse로 명칭 변경함

* feat: 공통 예외 스펙 추가

- 공통 예외 스펙과 exceptionHandler 추가

* chore: QueryDSL 세팅

* feat: 상위 목표 페이징 조회 기능 개발

- 커서 기반 페이지네이션을 사용
- Service 통합 테스트 후 Controller 개발 예정

* test: 상위 목표 페이징 조회 기능 테스트

- 테스트 데이터간 독립성을 위해 databaseCleaner 추가

* test: 페이징 기능 응답 스펙 변경

- 기존의 Slice의 반환 형식이 no offset 기반 페이징에서는 불필요하다고 판단되어 필요한 데이터만 파싱 처리함

* refactor: 상위 목표 통계 기능 삭제 및 테스트 수정

* feat: 상위 목표 상태별 개수 조회 기능 추가

- 기능 추가 및 테스트 진행 완료

* feat: 상위 목표 리스트에 dDay 컬럼 추가

- Swagger 어노테이션 수정

* feat: ErrorCode에 상위 목표 예외 추가

* test: GoalStatus 변경

* refactor: CustomResponse 오타 수정

* refactor: Swagger ApiResponse 제거

ApiResponse로 응답값을 제대로 표현할 수 없다고 판단되어 우선은 배제하기로 결정

* refactor: GlobalExceptionHandler 수정

* refactor: 클래스 내 빈공간 제거

* refactor: Tag와 Operation 재배치

* [Feature/#17] refresh token 발급 시 Redis에 저장하도록 설정 (#18)

* feat: Redis 저장소 추가 및 세팅 (#17)

* docs: @parameter 어노테이션으로  OAuthController 파라미터 설명 추가

* refactor: 소문자 provider를 대문자로 변경하는 함수 작성

* feat: OAuthController에 issue 메서드 추가 (#17)

* refactor: socialId를 uid로, socialType을 provider로 명칭 변경

socialId가 사실상 사용자 식별 필드로 사용된다. 그러나 문자열인 socialId를 PK로 두는 것은 한계가 있기 때문에 uid로 명칭을 변경한다. 또한, Provider와 SocialType 명칭도 겹치기 때문에 provider라는 단어로 통일한다

* feat: RefreshToken, RefreshTokenRepository 작성 (#17)

* feat: 액세스 토큰 만료 시 재발급 요청하는 reissue 서비스 코드 작성 (#17)

* feat: 로그인 시 refresh token을 redis에 저장하는 기능 추가 (#17)

* refactor: Auth 비즈니스 로직 Exception 처리

* feat: Redis 설정 수정

* refactor: login 호출 시 잘못된 provider가 입력되는 경우 예외처리

* test: reissue, login fail 테스트 케이스 추가 (#17)

* refactor: CustomResponse를 사용하여 Controller 반환

* feat: @Valid 어노테이션 추가

* ci: 배포 시 테스트되지 않도록 deploy.yml 수정

* build: build.yml에 Redis 설정 추가

* build: redis port 입력 방식 수정

* refactor: 풀 리퀘스트 리뷰 반영

---------

Co-authored-by: MingyeomKim <[email protected]>

* [Feature/#16] 하위 목표 기능 구현 (#20)

* feat: 상위 목표 d-day 기능 구현, 테스트 작성 (#6)

- 상위 목표 종료 일자 필수 입력으로 확정 후, d-day 계산 로직 plan 엔티티내 생성 후 테스트
- planService에 상위 목표 단건 조회 로직 추가

* feat: detail_goal 엔티티 설계 (#16)

* feat: detailGoal 엔티티 설계 (#16)

* feat: detailGoal 전체 조회 기능 구현 (#16)

* feat: detailGoal 전체 조회 Controller 구현

* feat: detailGoal 저장 기능 구현 (#16)

* refactor: 에러 코드 수정

- Goal 에러 코드 수정
- Detail Goal 에러 코드 추가

* feat: detail goal 상세 조회 응답값 변경 (#16)

- 요일 정보를 EnumSet으로 관리하는걸 생각했으나 엔티티에는 적용이 되지 않아 List로 관리하기로 결정

* refactor: detail goal 요청 시 요일 정보 string으로 변경

* feat: detail goal 추가 시 goal 내부 카운트 증가 로직 추가 (#16)

* feat: detail goal 수정, 삭제 기능 추가 (#16)

* feat: detail goal 달성, 달성 해제 기능 구현 (#16)

* test: detail goal 서비스 테스트 작성 (#16)

* refactor: application-prod.yml 임시 파일 삭제

* feat: detail goal, goal 조회 쿼리에 isDeleted 판별 조건 추가 (#16)

기본적으로 soft delete를 사용하기 때문에 isDeleted에 대한 판별 조건을 포함해야 한다

* feat: goal 삭제 시 연관 detail goal 삭제 로직 추가 (#16)

* feat: 전체 detail goal과 달성 detail goal 계산 및 조회 로직 추가 (#16)

* [Feature/#21] 보관함 복구 기능, 회고 개수 조회 기능 구현 (#22)

* feat: 상위 목표 d-day 기능 구현, 테스트 작성 (#6)

- 상위 목표 종료 일자 필수 입력으로 확정 후, d-day 계산 로직 plan 엔티티내 생성 후 테스트
- planService에 상위 목표 단건 조회 로직 추가

* 간격 수정

* feat: 상위 목표 복구 기능 구현 (#21)

* refactor: transactional 어노테이션 추가

* feat: LocalTime 요청 응답 값 오전/오후 반영하도록 변경 (#21)

* feat: 상위 목표 제약 조건 수정 (#21)

- 현재 보다 이전 날짜를 시작일로 선택 불가능하다는 조건이 없기에 조건 제거
- 보관함에서 복구 시 시작, 종료 날짜를 초기화 예정이기에 nullable을 true로 변경

* feat: 상위 목표 복구 기능 수정 (#21)

- 복구 시 새로운 데이터로 초기화해야 복구가 완료 되도록 설정

* feat: 회고 작성 가능한 완료 목표 개수 조회 (#21)

* feat: goal 생성시, goalstatus 생성자 주입으로 변경

- goalstatus 값을 변경해서 테스트 해야 할 경우들이 있다고 판단되어, 테스트 코드 편의성과 changeGoalStatus라는 setter 메서드를 제거하기 위해 작업을 진행함

* test: 테스트 작성 완료

* refactor: GoalController내 위치 변경

* application.yml 제거

* refactor: goalController 공통 URI 통일

* [Feature/#23] 하위 목표 모두 성공시 보상 제공 및 팝업 기능 구현 (#25)

* feat: 상위 목표 d-day 기능 구현, 테스트 작성 (#6)

- 상위 목표 종료 일자 필수 입력으로 확정 후, d-day 계산 로직 plan 엔티티내 생성 후 테스트
- planService에 상위 목표 단건 조회 로직 추가

* 간격 수정

* feat: 보상 제공 기능 구현 (#23)

* feat: 상위 목표 달성 시 팝업 기능 구현 (#23)

- 랜덤으로 보석 지급 기능 구현
- 상위 목표 리스트 조회 시 보석 enum도 조회 추가
- 보석 지급과 함께 complete 상태의 상위 목표 개수 조회

* test: 상위 목표 성공 시 기능 테스트 작성 (#23)

* refactor: 상위 목표 개수 반환값 및 주석 수정

* [Feature/#24] 채움함 내 상위 목표의 종료 기간 경과 시 보관함으로 이동하는 스케쥴러 구현 (#26)

* feat: 상위 목표 d-day 기능 구현, 테스트 작성 (#6)

- 상위 목표 종료 일자 필수 입력으로 확정 후, d-day 계산 로직 plan 엔티티내 생성 후 테스트
- planService에 상위 목표 단건 조회 로직 추가

* 간격 수정

* feat: 0시 0분에 호출되는 스케쥴러 구현 (#24)

* .gitignore 초기화

* test: 스케쥴러 테스트 작성

* test: 스케쥴러 테스트 작성 (#24)

* feat: cron 수정 (#24)

* Cicd test (#27)

* feat: 상위 목표 d-day 기능 구현, 테스트 작성 (#6)

- 상위 목표 종료 일자 필수 입력으로 확정 후, d-day 계산 로직 plan 엔티티내 생성 후 테스트
- planService에 상위 목표 단건 조회 로직 추가

* 간격 수정

* 서브 모듈 수정

* ci: redis container 설정 추가

* ci: SuperCharge의 Redis Server를 사용하도록 수정

* ci : build시 submodule을 가져오도록 설정

* ci: deploy 대상을 dev 브랜치로만 변경

* ci: deploy.yml의 submodule를 recursive로 설정

* ci: submodule 업데이트

* ci: dev profile로 빌드하도록 수정 및 submodule update 구문 추가

* [Feature/#19] 로그아웃, 회원 탈퇴 구현 및 Custom Filter 생성 후 Spring Security 적용 (#29)

* feat: 로그아웃 기능 추가 (#19)

* feat: Redis에 블랙 리스트 기능 추가 (#19)

* refactor: BlackList 도메인에서 status 제외

* feat: 회원 탈퇴 기능 구현 (#19)

* feat: reissue 시 refresh token도 새로 발급하도록 수정

* feat: Security Config 생성 및 OAuthController URI 통일

* feat: JwtFilter 구현 및 TokenProvider의 getAuthentication 작성

* feat: 인증, 인가 로직 실패 시 Exception Handler 작성

* feat: Q클래스 생성

* chore: SecurityConfig 작성

* feat: SecurityConfig 설정 추가

* test: TokenProviderTest의 멤버 호출 구문 Mocking

* ci: build.yml, deploy.yml에서 submodule 자동 업데이트하도록 수정

* refactor: 토큰 유효성 검사 중복 제거

* feat: 회원 탈퇴 시 블랙 리스트에 추가

* feat: jwtFilter에서 블랙리스트 조회하는 로직 추가

* refactor: OAuthController의 함수 명칭을 일관되게 변경

* build: 라이브러리 꼬임 해결

* ci: java 실행 시 sudo 권한 추가

* docs: swagger cors에러 수정

* chore: 모든 URL 접근 가능하도록 설정

* refactor: jwtFilter에서 예외 던지지 않도록 수정

* chore: 모든 경로 접근 허용

* chore: 모든 경로 접근 허용

* refactor: JwtFilter에서 모든 Exception을 제외

* refactor: CORS 에러 해결

* chore: swagger에 authorization 인증 받을 수 있도록 수정

* chore: SwaggerConfig 수정

* build: run_new_was.sh 스크립트 들여쓰기 수정

* chore: run_new_was.sh가 동작 확인을 위한 로그 출력

* build: run_new_was.sh 에서 구동할 포트를 죽이는 명령어 수정

* feat: 회원 탈퇴 컨트롤러 URL추가

* [Feature/#31] 유저 로그인 시 fcm token을 저장하는 로직 구현 (#32)

* feat: 로그인 시 fcm token을 함께 전달받도록 수정

* feat: Fcm Token 저장 및 조회 로직 추가

* [Feature/#28] 알림 요일과 시간에 따라 FCM 알림을 전송하는 기능 구현 (#35)

* feat: 상위 목표 d-day 기능 구현, 테스트 작성 (#6)

- 상위 목표 종료 일자 필수 입력으로 확정 후, d-day 계산 로직 plan 엔티티내 생성 후 테스트
- planService에 상위 목표 단건 조회 로직 추가

* 간격 수정

* 최신 사항 머지

* git cache 초기화

* feat: 푸시 알람 스케쥴러 구현 (#28)

- 매일 30분 간격으로 작동하는 스케쥴러 구현
- FCM 서비스를 호출하는 event 구현

* feat: 요일, 시간별 알림 전송 스케쥴러 구현 (#28)

* test: detailGoalQueryRepository 테스트 추가 (#28)

* refactor: 공통 응답 스펙 수정

* docs: swagger 문서 수정

* docs: 코드,메세지 설명 추가

* feat: 응답 Response에 Schema 추가 (#36)

* chore: 토큰의 만료시간 임의 변경

* locale (#39)

* fix: locale 수정

* JsonFormat pattern 변경 (#41)

* fix: localtime 형식 변경

* [Feature/#37] 회고 도메인 생성 및 저장, 조회 로직 구현 (#42)

* refactor: fcmToken 조회 로직 수정, logout, withdraw에 추가

* feat: 회고 도메인 생성 (#37)

* feat: 회고 도메인의 Repository 생성

* feat: 회고 저장 및 조회 로직 구현 (#37)

* feat: 회고의 내용을 담는 RetroSpectContent 분리 (#37)

* test: 회고 저장 및 조회 서비스 로직 테스트

* feat: 회고 저장 및 조회 컨트롤러 구현 (#37)

* refactor: 의존성 관련 오류 수정

* [Refactor/#37] 회고 기능 관련 리팩토링 (#44)

* LocalDate JSON 응답 형식 변경 (#45)

* refactor: GoalController LocalTime 형식 변경

* chore: JPA의 ddl-auto를 create로 설정

* build: 빌드 시 워크플로우에서 secrets 불러오는 것 제외

* feat: Retrospect Response에 hasGuide 컬럼 추가

* build: build.yml 워크플로우에서 서브모듈 로직 제외

* refactor: contents의 @column 삭제

* chore: run_new_was.sh의 내용 일부 수정

* chore: config의 application-dev.yml 수정

* refactor: Retrospect와 Content를 양방향 매핑으로 변경

* refactor: retrospect content가 retrospect를 가져오지 못하는 부분 수정

* chore: ddl-auto를 create로 변경

* [Feature/#38] FCM 푸시 알림 기능 연동 후 하위 목표 알림 스케쥴러와 연결한다 (#46)

* feat: FCM 알림 설정 및 연동 (#38)

* refactor: GoalController LocalTime 형식 변경

* feat: FCM 알림 스케쥴링 기능 복구

* refactor: 테스트 수정 및 도메인 디렉토리 구조 변경

* refactor: DetailGoal 수정 시 locale 정보 변경

* submodule내 FCM 설정 파일 경로 수정 (#50)

* fix: submodule에 fcm_key.json 경로 수정

* 하위 목표 시간 locale 응답 ko로 수정 (#51)

* refactor: 하위 목표 응답 시간 locale ko로 수정

* 상위 목표 개수 카운트 쿼리 수정 (#52)

- 삭제 여부 판단 로직을 쿼리의 having 부분에서 where 절로 옮김

* [Refactor/#47] 사용자 인증 필터에서 발생하는 예외 핸들러 필터 구현 (#49)

* feat: 예외를 발생시키는 JwtExceptionFilter 클래스 생성

* refactor: TokenProvider의 validateToken이 JwtException을 반환하도록 수정

* refactor: 따로 처리가 필요한 인증 예외 클래스를 생성하고, Token 검증 오류 시 Throw한다.

* feat: 블랙 리스트 Exception 클래스 생성, Authentication 필터 수정

* feat: 필터의 오류 핸들링 필터를 추가 (#47)

* feat: 인증 필터를 핸들링하는 필터 작성 (#47)

추가로 궁금한 점 :

(1) 토큰 만료 시 = reissue 요청
(2) 토큰이 없는 경우 = 로그인 요청
(3) 토큰이 잘못된 경우 = 올바르지 않다는 메시지 반환

이런 식으로 구현할려고 했는데, ErrorCode가 달라지는 것 말고는 별 다른 처리할 것이 없다고 생각해서 setErrorResponse 메소드 하나로 통일하여 예외를 처리하였다. 이렇게 획일화하고 나니 그냥 JwtException 하나로만 서로 다른 ErrorCode를 넣어서 구현해도 같은 결과를 가져올 것 같아서, Exception 클래스의 분리의 필요성을 못느꼈다.

* refactor: jwt 토큰의 유효성 검증은 따로 Exception 처리 제외

* chore: config 수정 사항 반영

* 상위 목표 수정 기능 Service 파라미터 수정 및 Security Config 변경 (#53)

* refactor: 상위 목표 수정 컨트롤러에서 Path Variable 사용하도록 변경

* refactor: SecurityConfig 설정 변경

* 기존에 전체 허용으로 열려있던 URL 경로 권한을 인증 URL로 제한

* Spring Security내 permitAll 동작할 수 있도록 JwtFilter 수정 (#54)

* refactor: permitAll한 url은 token 예외가 발생하지 않도록 처리

* GoalResponse @jsonformat 수정 (#55)

* refactor: GoalResponse의 JsonFormat 수정

* JWT 유효기간 수정 (#56)

* refactor: JWT 만료 시간 수정

* 하위 목표 수정 문제 해결 및 상위 목표 페이징 커서 수정 (#57)

* refactor: 페이징 커서 null에서 -1일때 전체 조회하도록 수정

* 회고 작성 시 보관함 내 목표 리마인드 기능 추가 (#58)

* feat: 보관함 목표 리마인드 기능 개발

* 상위 목표 리스트 조회 시 리마인드 여부 컬럼 추가 (#59)

* refactor: 상위 목표 리스트 반환 시 reminder 여부 컬럼 추가

* 보관함에 있는 목표 조회 시 d-day 0으로 계산 (#60)

* 보관함에 있는 목표 d-day 계산 시 0 반환하도록 변경

* 보관함에 있는 목표 조회 시 d-day 값을 음수로 반환 (#61)

* 보관함에 있는 목표 조회 시 d-day 값을 음수로 반환

* feat: 토큰 재발급 시, 재발급된 refresh token을 redis에 저장

* refactor: SecurityConfig 에서 exception Handling 제외

* refactor: reissue 시 refresh token을 조회할 수 없는 부분 수정

* hotfix: import 시 오타 수정

* refactor: /auth 경로를 Authentication Filter를 거치지 않도록 설정

* hotfix: URI와 Request Method 확인을 위한 로깅 처리

* refactor: 허용한 URL 이외의 요청에 인증을 거치도록 설정

* feat: 상위 목표, 세부 목표 API JWT 인증 거치도록 설정

* feat: 최초 로그인 시 관련 정보를 함께 Response에 전달

* 인증 유저 정보를 사용해서 사용자 상위 목표를 식별한다 (#62)

- @AuthenticationPrincipal을 통해 인증 유저 식별자 가져옴

* refactor: 재로그인 시 refresh, fcm token 삭제하는 코드 제거

* refactor: 애플리케이션 실행 시 Asia/Seoul Timezone 설정

* test: 토큰 테스트를 위해 유효 기간을 짧게 설정

* refactor: 저장되지 않은 토큰 입력 시 401 에러 반환하도록 수정

* refactor: 토큰의 유효시간 정상화

* test: 토큰 유효시간 짧게 설정

* refactor: 리프레시 토큰 유효기간 정상화

* test: reissue 테스트를 위한 로그 추가

* refactor: refresh Token 객체 timeToLive설정

* refactor: @column에 unique=true를 추가하여 해결 (#65)

* refactor: 토큰 유효시간 정상화

* 목표 달성 후 보상 지급 시, 로그인한 사용자의 달성 목표만 카운트 하도록 설정한다 (#66)

* refactor: 보상 지급 시 달성 목표 카운트 수정

---------

Co-authored-by: Seo Jemin <[email protected]>
Co-authored-by: MingyeomKim <[email protected]>
Mingyum-Kim added a commit that referenced this pull request Sep 17, 2023
* 상위 목표 엔티티 구현 (#5)

* chore: Lombok, JPA 의존성 추가

* feat: plan 엔티티 내 유효성 검사 구현

* feat: PlanRepository 생성

* test: plan 엔티티 테스트 작성

- 상위 목표 제목 길이 validation 테스트
- 상위 목표 시작, 달성 날짜 validation 테스트
- 상위 목표 제목 길이 Figma 참고해서 15자 제한

* feat: 상위 목표 기간 LocalDate 타입으로 변경 (#3)

기간을 설정할때 연월일 까지만 데이터를 받기에 시,분까지 데이터를 받는 LocalDateTime은 불필요하다고 판단했음.

* [Feature/#2] 소셜 로그인 구현 (#4)

* feat: BaseEntity 작성

global/entity 폴더에 created_at, updated_at 필드를 넣는 BaseEntity 클래스를 작성하였습니다.

* feat: User Entity 생성 (#2)

DB에 매핑될 User 객체를 생성하였습니다. Kakao, Apple 두 개의 소셜 타입을 구분할 SocialType 필드를 enum Type으로 추가하였습니다.

* chore: Swagger, Logging 클래스 global 폴더로 이동

* feat: OAuthController 생성 및 콜백 메서드 생성

1. 클라이언트가 AccessToken을 전달할 때 접근하는 'POST /auth' 콜백 주소를 연결할 메서드를 생성하였습니다.
2. 컨트롤러 메서드의 request, response dto를 record 클래스로 정의하였습니다.

* feat: login 로직을 구현한 OAuthService 생성

1. 팩토리 메서드 패턴을 적용하여 OAuthClient 인터페이스를 provider에 따라 구현체를 매핑하도록 설정하였습니다.
2. OAuthClient에서 소셜 사용자의 정보를 불러오고 User 객체로 변환하였습니다.
3. User가 기 가입한 회원이라면 바로 반환, 그렇지 않다면 DB에 등록 후 반환하기 위해 UserService에서 로직을 구현하였습니다.
4. 마지막으로 회원에 대한 JWT 를 발급하여 반환하였습니다.

* build: syntax error 수정

* build: syntax error 수정

* build: Junit Test 관련 권한 추가

* feat: WebClient를 이용해 카카오 인증서버에서 사용자 추출 (#2)

KakaoClient 구현체에서 WebClient 라이브러리를 사용해 kapi.kakao.com 서버에 접근하여 사용자 정보 (KakaoUserInfo)를 추출하는 코드입니다.

* feat: JwtProvider 클래스 생성

1. createToken 메서드
2. validateToken 메서드

* chore: .gitignore 수정

* feat: 애플 로그인 구현

* refactor: OAuthHandler에서 Provider별 클래스 분리 구현

* test: OAuthServiceTest 로그인 성공 테스트 생성(#2)

* feat: KakaoClient BASE_URL과 URI 분리

* style: dto 폴더구조 request, response 나눠서 변경

* refactor: SocialId만 이용해서 사용자 조회하도록 변경

* refactor: BaseEntity에 자동으로 날짜를 주입하도록 설정

---------

Co-authored-by: MingyeomKim <[email protected]>

* [Feature/#7] 설정 파일 submodule로 관리 (#8)

* build: db 정보 암호화를 위한 submodules 설정(#7)

* build: github Secrets 설정 수정

* fix: build.yml의 들여쓰기 오류 수정

* feat: 빌드 시 submodule 설정 파일 불러올 수 있도록 build.gradle 수정

* build: deploy.yml ACTION_TOKEN 추가

* build: build.gradle 라이브러리 중복 제거

* "build: build.gradle에 active profile 설정 추가 (#7) "

* feat: dev 환경 데이터베이스 설정 추가

* build: dev 환경에서 빌드되도록 수정

* fix: build.yml의 test 명령어 수정

* fix: build.yml의 Publish unit test r구문 수정

* fix: build.yml test 파일 경로 수정"

* "build: test 시 h2 database에서 작동하도록 application-tets.yml 추가

* chore: .gitignore 수정

* build: test profile을 test로 변경

* test: config 설정 수정

* build: build.yml의 Publish Unit Test Results에 토큰 추가

* build: test-results files 경로 수정

* build: github actions permissions를 write 권한으로 변경

* build: build.yml에 issues: write 권한 추가

* refactor: User 명칭을 Member로 변경

---------

Co-authored-by: MingyeomKim <[email protected]>

* [Feature/#6] 공통 응답 추가 및 상위 목표 단건 조회 기능 구현 (#9)

* feat: 상위 목표 d-day 기능 구현, 테스트 작성 (#6)

- 상위 목표 종료 일자 필수 입력으로 확정 후, d-day 계산 로직 plan 엔티티내 생성 후 테스트
- planService에 상위 목표 단건 조회 로직 추가

* feat: 공통 응답 스펙 추가

* feat: 상위 목표 삭제 기능 추가

- Service에 삭제 기능 추가, 차후 테스트 필요
- 상위 목표 생성 Controller DTO 추가

* chore: application.yml 수정

* test: CI 테스트

* refactor: controller내 pathVariable 제거

* chore: build.yml을 테스트 환경에서 동작하도록 수정

* refactor: 소셜 로그인 시 input을 userId로 맞추어 수정 (#11) (#12)

Co-authored-by: MingyeomKim <[email protected]>

* [Feature/#13] TokenProvider 클래스 생성 및 Refresh Token 반환 (#14)

* feat: Refresh token을 생성하도록 TokenProvider 클래스 추가

* test: TokenProvider 단위 테스트 생성

* test: TokenProviderTest 오류 수정

---------

Co-authored-by: MingyeomKim <[email protected]>

* [Feature/#10] 상위 목표 리스트 조회 기능 구현 (#15)

* feat: 상위 목표 d-day 기능 구현, 테스트 작성 (#6)

- 상위 목표 종료 일자 필수 입력으로 확정 후, d-day 계산 로직 plan 엔티티내 생성 후 테스트
- planService에 상위 목표 단건 조회 로직 추가

* chore: git 캐시 초기화

* feat: 상위 목표 생성, 수정 기능 구현 (#10)

* refactor: 상위 목표 도메인 명을 Plan에서 Goal로 변경

- Goal이라는 단어가 목표라는 의미를 더 잘 표현하는 것 같아서 변경하게 되었습니다

* refactor: 공통 응답 스펙명 CustomResponse로 변경

- Swagger에 있는 ApiResponse와 네이밍이 같아서 패키지 명 전체를 명시해야 함. 따라서 customResponse로 명칭 변경함

* feat: 공통 예외 스펙 추가

- 공통 예외 스펙과 exceptionHandler 추가

* chore: QueryDSL 세팅

* feat: 상위 목표 페이징 조회 기능 개발

- 커서 기반 페이지네이션을 사용
- Service 통합 테스트 후 Controller 개발 예정

* test: 상위 목표 페이징 조회 기능 테스트

- 테스트 데이터간 독립성을 위해 databaseCleaner 추가

* test: 페이징 기능 응답 스펙 변경

- 기존의 Slice의 반환 형식이 no offset 기반 페이징에서는 불필요하다고 판단되어 필요한 데이터만 파싱 처리함

* refactor: 상위 목표 통계 기능 삭제 및 테스트 수정

* feat: 상위 목표 상태별 개수 조회 기능 추가

- 기능 추가 및 테스트 진행 완료

* feat: 상위 목표 리스트에 dDay 컬럼 추가

- Swagger 어노테이션 수정

* feat: ErrorCode에 상위 목표 예외 추가

* test: GoalStatus 변경

* refactor: CustomResponse 오타 수정

* refactor: Swagger ApiResponse 제거

ApiResponse로 응답값을 제대로 표현할 수 없다고 판단되어 우선은 배제하기로 결정

* refactor: GlobalExceptionHandler 수정

* refactor: 클래스 내 빈공간 제거

* refactor: Tag와 Operation 재배치

* [Feature/#17] refresh token 발급 시 Redis에 저장하도록 설정 (#18)

* feat: Redis 저장소 추가 및 세팅 (#17)

* docs: @parameter 어노테이션으로  OAuthController 파라미터 설명 추가

* refactor: 소문자 provider를 대문자로 변경하는 함수 작성

* feat: OAuthController에 issue 메서드 추가 (#17)

* refactor: socialId를 uid로, socialType을 provider로 명칭 변경

socialId가 사실상 사용자 식별 필드로 사용된다. 그러나 문자열인 socialId를 PK로 두는 것은 한계가 있기 때문에 uid로 명칭을 변경한다. 또한, Provider와 SocialType 명칭도 겹치기 때문에 provider라는 단어로 통일한다

* feat: RefreshToken, RefreshTokenRepository 작성 (#17)

* feat: 액세스 토큰 만료 시 재발급 요청하는 reissue 서비스 코드 작성 (#17)

* feat: 로그인 시 refresh token을 redis에 저장하는 기능 추가 (#17)

* refactor: Auth 비즈니스 로직 Exception 처리

* feat: Redis 설정 수정

* refactor: login 호출 시 잘못된 provider가 입력되는 경우 예외처리

* test: reissue, login fail 테스트 케이스 추가 (#17)

* refactor: CustomResponse를 사용하여 Controller 반환

* feat: @Valid 어노테이션 추가

* ci: 배포 시 테스트되지 않도록 deploy.yml 수정

* build: build.yml에 Redis 설정 추가

* build: redis port 입력 방식 수정

* refactor: 풀 리퀘스트 리뷰 반영

---------

Co-authored-by: MingyeomKim <[email protected]>

* [Feature/#16] 하위 목표 기능 구현 (#20)

* feat: 상위 목표 d-day 기능 구현, 테스트 작성 (#6)

- 상위 목표 종료 일자 필수 입력으로 확정 후, d-day 계산 로직 plan 엔티티내 생성 후 테스트
- planService에 상위 목표 단건 조회 로직 추가

* feat: detail_goal 엔티티 설계 (#16)

* feat: detailGoal 엔티티 설계 (#16)

* feat: detailGoal 전체 조회 기능 구현 (#16)

* feat: detailGoal 전체 조회 Controller 구현

* feat: detailGoal 저장 기능 구현 (#16)

* refactor: 에러 코드 수정

- Goal 에러 코드 수정
- Detail Goal 에러 코드 추가

* feat: detail goal 상세 조회 응답값 변경 (#16)

- 요일 정보를 EnumSet으로 관리하는걸 생각했으나 엔티티에는 적용이 되지 않아 List로 관리하기로 결정

* refactor: detail goal 요청 시 요일 정보 string으로 변경

* feat: detail goal 추가 시 goal 내부 카운트 증가 로직 추가 (#16)

* feat: detail goal 수정, 삭제 기능 추가 (#16)

* feat: detail goal 달성, 달성 해제 기능 구현 (#16)

* test: detail goal 서비스 테스트 작성 (#16)

* refactor: application-prod.yml 임시 파일 삭제

* feat: detail goal, goal 조회 쿼리에 isDeleted 판별 조건 추가 (#16)

기본적으로 soft delete를 사용하기 때문에 isDeleted에 대한 판별 조건을 포함해야 한다

* feat: goal 삭제 시 연관 detail goal 삭제 로직 추가 (#16)

* feat: 전체 detail goal과 달성 detail goal 계산 및 조회 로직 추가 (#16)

* [Feature/#21] 보관함 복구 기능, 회고 개수 조회 기능 구현 (#22)

* feat: 상위 목표 d-day 기능 구현, 테스트 작성 (#6)

- 상위 목표 종료 일자 필수 입력으로 확정 후, d-day 계산 로직 plan 엔티티내 생성 후 테스트
- planService에 상위 목표 단건 조회 로직 추가

* 간격 수정

* feat: 상위 목표 복구 기능 구현 (#21)

* refactor: transactional 어노테이션 추가

* feat: LocalTime 요청 응답 값 오전/오후 반영하도록 변경 (#21)

* feat: 상위 목표 제약 조건 수정 (#21)

- 현재 보다 이전 날짜를 시작일로 선택 불가능하다는 조건이 없기에 조건 제거
- 보관함에서 복구 시 시작, 종료 날짜를 초기화 예정이기에 nullable을 true로 변경

* feat: 상위 목표 복구 기능 수정 (#21)

- 복구 시 새로운 데이터로 초기화해야 복구가 완료 되도록 설정

* feat: 회고 작성 가능한 완료 목표 개수 조회 (#21)

* feat: goal 생성시, goalstatus 생성자 주입으로 변경

- goalstatus 값을 변경해서 테스트 해야 할 경우들이 있다고 판단되어, 테스트 코드 편의성과 changeGoalStatus라는 setter 메서드를 제거하기 위해 작업을 진행함

* test: 테스트 작성 완료

* refactor: GoalController내 위치 변경

* application.yml 제거

* refactor: goalController 공통 URI 통일

* [Feature/#23] 하위 목표 모두 성공시 보상 제공 및 팝업 기능 구현 (#25)

* feat: 상위 목표 d-day 기능 구현, 테스트 작성 (#6)

- 상위 목표 종료 일자 필수 입력으로 확정 후, d-day 계산 로직 plan 엔티티내 생성 후 테스트
- planService에 상위 목표 단건 조회 로직 추가

* 간격 수정

* feat: 보상 제공 기능 구현 (#23)

* feat: 상위 목표 달성 시 팝업 기능 구현 (#23)

- 랜덤으로 보석 지급 기능 구현
- 상위 목표 리스트 조회 시 보석 enum도 조회 추가
- 보석 지급과 함께 complete 상태의 상위 목표 개수 조회

* test: 상위 목표 성공 시 기능 테스트 작성 (#23)

* refactor: 상위 목표 개수 반환값 및 주석 수정

* [Feature/#24] 채움함 내 상위 목표의 종료 기간 경과 시 보관함으로 이동하는 스케쥴러 구현 (#26)

* feat: 상위 목표 d-day 기능 구현, 테스트 작성 (#6)

- 상위 목표 종료 일자 필수 입력으로 확정 후, d-day 계산 로직 plan 엔티티내 생성 후 테스트
- planService에 상위 목표 단건 조회 로직 추가

* 간격 수정

* feat: 0시 0분에 호출되는 스케쥴러 구현 (#24)

* .gitignore 초기화

* test: 스케쥴러 테스트 작성

* test: 스케쥴러 테스트 작성 (#24)

* feat: cron 수정 (#24)

* Cicd test (#27)

* feat: 상위 목표 d-day 기능 구현, 테스트 작성 (#6)

- 상위 목표 종료 일자 필수 입력으로 확정 후, d-day 계산 로직 plan 엔티티내 생성 후 테스트
- planService에 상위 목표 단건 조회 로직 추가

* 간격 수정

* 서브 모듈 수정

* ci: redis container 설정 추가

* ci: SuperCharge의 Redis Server를 사용하도록 수정

* ci : build시 submodule을 가져오도록 설정

* ci: deploy 대상을 dev 브랜치로만 변경

* ci: deploy.yml의 submodule를 recursive로 설정

* ci: submodule 업데이트

* ci: dev profile로 빌드하도록 수정 및 submodule update 구문 추가

* [Feature/#19] 로그아웃, 회원 탈퇴 구현 및 Custom Filter 생성 후 Spring Security 적용 (#29)

* feat: 로그아웃 기능 추가 (#19)

* feat: Redis에 블랙 리스트 기능 추가 (#19)

* refactor: BlackList 도메인에서 status 제외

* feat: 회원 탈퇴 기능 구현 (#19)

* feat: reissue 시 refresh token도 새로 발급하도록 수정

* feat: Security Config 생성 및 OAuthController URI 통일

* feat: JwtFilter 구현 및 TokenProvider의 getAuthentication 작성

* feat: 인증, 인가 로직 실패 시 Exception Handler 작성

* feat: Q클래스 생성

* chore: SecurityConfig 작성

* feat: SecurityConfig 설정 추가

* test: TokenProviderTest의 멤버 호출 구문 Mocking

* ci: build.yml, deploy.yml에서 submodule 자동 업데이트하도록 수정

* refactor: 토큰 유효성 검사 중복 제거

* feat: 회원 탈퇴 시 블랙 리스트에 추가

* feat: jwtFilter에서 블랙리스트 조회하는 로직 추가

* refactor: OAuthController의 함수 명칭을 일관되게 변경

* build: 라이브러리 꼬임 해결

* ci: java 실행 시 sudo 권한 추가

* docs: swagger cors에러 수정

* chore: 모든 URL 접근 가능하도록 설정

* refactor: jwtFilter에서 예외 던지지 않도록 수정

* chore: 모든 경로 접근 허용

* chore: 모든 경로 접근 허용

* refactor: JwtFilter에서 모든 Exception을 제외

* refactor: CORS 에러 해결

* chore: swagger에 authorization 인증 받을 수 있도록 수정

* chore: SwaggerConfig 수정

* build: run_new_was.sh 스크립트 들여쓰기 수정

* chore: run_new_was.sh가 동작 확인을 위한 로그 출력

* build: run_new_was.sh 에서 구동할 포트를 죽이는 명령어 수정

* feat: 회원 탈퇴 컨트롤러 URL추가

* [Feature/#31] 유저 로그인 시 fcm token을 저장하는 로직 구현 (#32)

* feat: 로그인 시 fcm token을 함께 전달받도록 수정

* feat: Fcm Token 저장 및 조회 로직 추가

* [Feature/#28] 알림 요일과 시간에 따라 FCM 알림을 전송하는 기능 구현 (#35)

* feat: 상위 목표 d-day 기능 구현, 테스트 작성 (#6)

- 상위 목표 종료 일자 필수 입력으로 확정 후, d-day 계산 로직 plan 엔티티내 생성 후 테스트
- planService에 상위 목표 단건 조회 로직 추가

* 간격 수정

* 최신 사항 머지

* git cache 초기화

* feat: 푸시 알람 스케쥴러 구현 (#28)

- 매일 30분 간격으로 작동하는 스케쥴러 구현
- FCM 서비스를 호출하는 event 구현

* feat: 요일, 시간별 알림 전송 스케쥴러 구현 (#28)

* test: detailGoalQueryRepository 테스트 추가 (#28)

* refactor: 공통 응답 스펙 수정

* docs: swagger 문서 수정

* docs: 코드,메세지 설명 추가

* feat: 응답 Response에 Schema 추가 (#36)

* chore: 토큰의 만료시간 임의 변경

* locale (#39)

* fix: locale 수정

* JsonFormat pattern 변경 (#41)

* fix: localtime 형식 변경

* [Feature/#37] 회고 도메인 생성 및 저장, 조회 로직 구현 (#42)

* refactor: fcmToken 조회 로직 수정, logout, withdraw에 추가

* feat: 회고 도메인 생성 (#37)

* feat: 회고 도메인의 Repository 생성

* feat: 회고 저장 및 조회 로직 구현 (#37)

* feat: 회고의 내용을 담는 RetroSpectContent 분리 (#37)

* test: 회고 저장 및 조회 서비스 로직 테스트

* feat: 회고 저장 및 조회 컨트롤러 구현 (#37)

* refactor: 의존성 관련 오류 수정

* [Refactor/#37] 회고 기능 관련 리팩토링 (#44)

* LocalDate JSON 응답 형식 변경 (#45)

* refactor: GoalController LocalTime 형식 변경

* chore: JPA의 ddl-auto를 create로 설정

* build: 빌드 시 워크플로우에서 secrets 불러오는 것 제외

* feat: Retrospect Response에 hasGuide 컬럼 추가

* build: build.yml 워크플로우에서 서브모듈 로직 제외

* refactor: contents의 @column 삭제

* chore: run_new_was.sh의 내용 일부 수정

* chore: config의 application-dev.yml 수정

* refactor: Retrospect와 Content를 양방향 매핑으로 변경

* refactor: retrospect content가 retrospect를 가져오지 못하는 부분 수정

* chore: ddl-auto를 create로 변경

* [Feature/#38] FCM 푸시 알림 기능 연동 후 하위 목표 알림 스케쥴러와 연결한다 (#46)

* feat: FCM 알림 설정 및 연동 (#38)

* refactor: GoalController LocalTime 형식 변경

* feat: FCM 알림 스케쥴링 기능 복구

* refactor: 테스트 수정 및 도메인 디렉토리 구조 변경

* refactor: DetailGoal 수정 시 locale 정보 변경

* submodule내 FCM 설정 파일 경로 수정 (#50)

* fix: submodule에 fcm_key.json 경로 수정

* 하위 목표 시간 locale 응답 ko로 수정 (#51)

* refactor: 하위 목표 응답 시간 locale ko로 수정

* 상위 목표 개수 카운트 쿼리 수정 (#52)

- 삭제 여부 판단 로직을 쿼리의 having 부분에서 where 절로 옮김

* [Refactor/#47] 사용자 인증 필터에서 발생하는 예외 핸들러 필터 구현 (#49)

* feat: 예외를 발생시키는 JwtExceptionFilter 클래스 생성

* refactor: TokenProvider의 validateToken이 JwtException을 반환하도록 수정

* refactor: 따로 처리가 필요한 인증 예외 클래스를 생성하고, Token 검증 오류 시 Throw한다.

* feat: 블랙 리스트 Exception 클래스 생성, Authentication 필터 수정

* feat: 필터의 오류 핸들링 필터를 추가 (#47)

* feat: 인증 필터를 핸들링하는 필터 작성 (#47)

추가로 궁금한 점 :

(1) 토큰 만료 시 = reissue 요청
(2) 토큰이 없는 경우 = 로그인 요청
(3) 토큰이 잘못된 경우 = 올바르지 않다는 메시지 반환

이런 식으로 구현할려고 했는데, ErrorCode가 달라지는 것 말고는 별 다른 처리할 것이 없다고 생각해서 setErrorResponse 메소드 하나로 통일하여 예외를 처리하였다. 이렇게 획일화하고 나니 그냥 JwtException 하나로만 서로 다른 ErrorCode를 넣어서 구현해도 같은 결과를 가져올 것 같아서, Exception 클래스의 분리의 필요성을 못느꼈다.

* refactor: jwt 토큰의 유효성 검증은 따로 Exception 처리 제외

* chore: config 수정 사항 반영

* 상위 목표 수정 기능 Service 파라미터 수정 및 Security Config 변경 (#53)

* refactor: 상위 목표 수정 컨트롤러에서 Path Variable 사용하도록 변경

* refactor: SecurityConfig 설정 변경

* 기존에 전체 허용으로 열려있던 URL 경로 권한을 인증 URL로 제한

* Spring Security내 permitAll 동작할 수 있도록 JwtFilter 수정 (#54)

* refactor: permitAll한 url은 token 예외가 발생하지 않도록 처리

* GoalResponse @jsonformat 수정 (#55)

* refactor: GoalResponse의 JsonFormat 수정

* JWT 유효기간 수정 (#56)

* refactor: JWT 만료 시간 수정

* 하위 목표 수정 문제 해결 및 상위 목표 페이징 커서 수정 (#57)

* refactor: 페이징 커서 null에서 -1일때 전체 조회하도록 수정

* 회고 작성 시 보관함 내 목표 리마인드 기능 추가 (#58)

* feat: 보관함 목표 리마인드 기능 개발

* 상위 목표 리스트 조회 시 리마인드 여부 컬럼 추가 (#59)

* refactor: 상위 목표 리스트 반환 시 reminder 여부 컬럼 추가

* 보관함에 있는 목표 조회 시 d-day 0으로 계산 (#60)

* 보관함에 있는 목표 d-day 계산 시 0 반환하도록 변경

* 보관함에 있는 목표 조회 시 d-day 값을 음수로 반환 (#61)

* 보관함에 있는 목표 조회 시 d-day 값을 음수로 반환

* feat: 토큰 재발급 시, 재발급된 refresh token을 redis에 저장

* refactor: SecurityConfig 에서 exception Handling 제외

* refactor: reissue 시 refresh token을 조회할 수 없는 부분 수정

* hotfix: import 시 오타 수정

* refactor: /auth 경로를 Authentication Filter를 거치지 않도록 설정

* hotfix: URI와 Request Method 확인을 위한 로깅 처리

* refactor: 허용한 URL 이외의 요청에 인증을 거치도록 설정

* feat: 상위 목표, 세부 목표 API JWT 인증 거치도록 설정

* feat: 최초 로그인 시 관련 정보를 함께 Response에 전달

* 인증 유저 정보를 사용해서 사용자 상위 목표를 식별한다 (#62)

- @AuthenticationPrincipal을 통해 인증 유저 식별자 가져옴

* refactor: 재로그인 시 refresh, fcm token 삭제하는 코드 제거

* refactor: 애플리케이션 실행 시 Asia/Seoul Timezone 설정

* test: 토큰 테스트를 위해 유효 기간을 짧게 설정

* refactor: 저장되지 않은 토큰 입력 시 401 에러 반환하도록 수정

* refactor: 토큰의 유효시간 정상화

* test: 토큰 유효시간 짧게 설정

* refactor: 리프레시 토큰 유효기간 정상화

* test: reissue 테스트를 위한 로그 추가

* refactor: refresh Token 객체 timeToLive설정

* refactor: @column에 unique=true를 추가하여 해결 (#65)

* refactor: 토큰 유효시간 정상화

* 목표 달성 후 보상 지급 시, 로그인한 사용자의 달성 목표만 카운트 하도록 설정한다 (#66)

* refactor: 보상 지급 시 달성 목표 카운트 수정

* feat: 토큰 관리 API 추가 (#68)

Co-authored-by: MingyeomKim <[email protected]>

---------

Co-authored-by: Seo Jemin <[email protected]>
Co-authored-by: MingyeomKim <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants